#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>

// 定义定时发送的数据
const char *bg_message = "BG,..,..,..,..,ED\n";

// #define SERVER_IP "180.166.31.254"  // 服务器IP地址
// #define PORT 40199                  // 服务器端口

#define SERVER_IP "8.135.10.183"  // 服务器IP地址
#define PORT 36566                  // 服务器端口

#define BUFFER_SIZE 1024          // 缓冲区大小
#define HEARTBEAT_INTERVAL 60      // 心跳间隔（秒）
#define RECONNECT_BASE_DELAY 1    // 重连基准时间（秒）
#define MAX_RECONNECT_ATTEMPTS 5  // 最大重连尝试次数S


typedef struct {
    int sock;                // socket文件描述符
    int is_connected;        // 是否已连接
    int reconnect_attempts;  // 重连尝试次数
    time_t last_activity;    // 上次活动时间
    time_t last_bg_send;     // 上次发送BG消息的时间
    pthread_mutex_t lock;    // 互斥锁，用于保护共享资源
    pthread_cond_t cond;     // 新增条件变量
} ConnectionState;

void connection_init(ConnectionState *conn) {
    conn->sock = -1;
    conn->is_connected = 0;
    conn->reconnect_attempts = 0;
    conn->last_activity = 0;
    conn->last_bg_send = 0;
    pthread_mutex_init(&conn->lock, NULL);
    pthread_cond_init(&conn->cond, NULL);  // 初始化条件变量
}

// 创建socket
int create_socket() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        return -1;
    }

    // 设置发送超时（可选）
    struct timeval tv_send = {.tv_sec = 5, .tv_usec = 0};
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv_send, sizeof(tv_send));
    
    return sock;
}

// 连接到服务器
int connect_to_server(int sock) {
    struct sockaddr_in server_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(PORT)
    };

    // 将IP地址从文本转换为二进制形式
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("Invalid address");
        return -1;
    }

    struct timeval tv_connect = {.tv_sec = 5, .tv_usec = 0};
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv_connect, sizeof(tv_connect));
    
    // 尝试连接到服务器
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        return -1;
    }
    return 0;
}

// 接收线程函数
void* receiver_thread(void* arg) {
    ConnectionState *conn = (ConnectionState*)arg;
    char buffer[BUFFER_SIZE];

    while (1) {
        pthread_mutex_lock(&conn->lock);
        
        // 等待连接建立
        while (!conn->is_connected) {
            pthread_cond_wait(&conn->cond, &conn->lock);
        }

        // 设置接收超时
        struct timeval tv = {.tv_sec = 1, .tv_usec = 0};
        setsockopt(conn->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

        ssize_t valread = recv(conn->sock, buffer, BUFFER_SIZE, 0);
        if (valread > 0) {
            buffer[valread] = '\0';
            printf("[Receiv] Received %zd bytes: %s\n", valread, buffer);
            conn->last_activity = time(NULL);
        } else if (valread == 0) {
            printf("[Receiv] Connection closed by server\n");
            close(conn->sock);
            conn->is_connected = 0;
            pthread_cond_signal(&conn->cond); // 通知发送线程
        } else {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                perror("[Receiv] Error");
                printf("Error code: %d\n", errno);  // 打印错误码
                close(conn->sock);
                conn->is_connected = 0;
                pthread_cond_signal(&conn->cond);
            }
        }

        pthread_mutex_unlock(&conn->lock);
        sleep(1); // 100ms间隔
    }
    return NULL;
}

// 发送线程函数
void* sender_thread(void* arg) {
    ConnectionState *conn = (ConnectionState*)arg;

    while (1) {
        pthread_mutex_lock(&conn->lock);

        // 连接管理
        if (!conn->is_connected) {
            int delay = RECONNECT_BASE_DELAY << conn->reconnect_attempts;
            printf("[Sender] Reconnecting in %ds...\n", delay);
            
            pthread_mutex_unlock(&conn->lock);
            sleep(delay);
            pthread_mutex_lock(&conn->lock);

            if ((conn->sock = create_socket()) == -1 ||
                connect_to_server(conn->sock) == -1) {
                close(conn->sock);
                conn->sock = -1;
                if (conn->reconnect_attempts < MAX_RECONNECT_ATTEMPTS) {
                    conn->reconnect_attempts++;
                }
                pthread_mutex_unlock(&conn->lock);
                continue;
            }

            printf("[Sender] Connected successfully\n");
            conn->is_connected = 1;
            conn->reconnect_attempts = 0;
            conn->last_activity = time(NULL);
            pthread_cond_signal(&conn->cond); // 通知接收线程
        }

        // // 心跳检测
        // if (time(NULL) - conn->last_activity > HEARTBEAT_INTERVAL) {
        //     const char *heartbeat = "HEARTBEAT\n";
        //     if (send(conn->sock, heartbeat, strlen(heartbeat), 0) < 0) {
        //         perror("[Sender] Heartbeat failed");
        //         close(conn->sock);
        //         conn->is_connected = 0;
        //     } else {
        //         conn->last_activity = time(NULL);
        //         printf("[Sender] Sent heartbeat\n");
        //     }
        // }

        // BG消息发送
        time_t now = time(NULL);
        if (now - conn->last_bg_send >= 28) {
            ssize_t sent = send(conn->sock, bg_message, strlen(bg_message), 0);
            if (sent < 0) {
                perror("[Sender] BG send failed");
                close(conn->sock);
                conn->is_connected = 0;
            } else {
                printf("[Sender] Sent BG message (%zd bytes)\n", sent);
                conn->last_bg_send = now;
                conn->last_activity = now;
            }
        }

        pthread_mutex_unlock(&conn->lock);
        sleep(1);
    }
    return NULL;
}

int main() {
    ConnectionState conn;
    connection_init(&conn);

    pthread_t sender_tid, receiver_tid;

    // 创建发送线程
    if (pthread_create(&sender_tid, NULL, sender_thread, &conn) != 0) {
        perror("Sender thread create failed");
        exit(EXIT_FAILURE);
    }

    // 创建接收线程
    if (pthread_create(&receiver_tid, NULL, receiver_thread, &conn) != 0) {
        perror("Receiver thread create failed");
        exit(EXIT_FAILURE);
    }

    // 主线程监控
    while (1) {
        sleep(10);
        pthread_mutex_lock(&conn.lock);
        printf("[Monito] Status: %s, Socket: %d\n", 
              conn.is_connected ? "Connected" : "Disconnected",
              conn.sock);
        pthread_mutex_unlock(&conn.lock);
    }

    // 实际应用中需要添加退出逻辑
    pthread_join(sender_tid, NULL);
    pthread_join(receiver_tid, NULL);
    pthread_mutex_destroy(&conn.lock);
    pthread_cond_destroy(&conn.cond);
    return 0;
}